--
-- Setup Alterac Valley.
--
function CattleProd_SetupAlteracValley()
	CattleProd_Report(CattleProd_REPORT_LEVEL_MEDIUM,
		"Setup: %s", CattleProd_LocaleString(CattleProd_ZONE_ALTERAC_VALLEY));

	-- player scoreboard function
	CattleProd_GetBattlegroundScoreboardMap_Function = CattleProd_GetAlteracValleyScoreboardMap;

	-- get defensible positions map
	CattleProd_GetBattlegroundDefensiblePositionsMap_Function = CattleProd_AlteracValleyDefensiblePositionsMap;

	-- get battleground player scoreboard effort
	CattleProd_CalculateBattlegroundScoreboardEffort_Function = CattleProd_CalculateAlteracValleyScoreboardEffort;

	-- get defensive range
	CattleProd_GetBattlegroundDefensiveRange_Function = CattleProd_GetAlteracValleyDefensiveRange;

	-- calculate battleground defender effort
	CattleProd_CalculateBattlegroundDefenderEffort_Function = CattleProd_CalculateAlteracValleyDefenderEffort;
end

--
-- Constant: Alterac Valley Graveyards Assaulted
--
CattleProd_ALTERAC_VALLEY_GRAVEYARDS_ASSAULTED = 1;

--
-- Constant: Alterac Valley Graveyards Defended
--
CattleProd_ALTERAC_VALLEY_GRAVEYARDS_DEFENDED = 2;

--
-- Constant: Alterac Valley Towers Assaulted
--
CattleProd_ALTERAC_VALLEY_TOWERS_ASSAULTED = 3;

--
-- Constant: Alterac Valley Towers Defended
--
CattleProd_ALTERAC_VALLEY_TOWERS_DEFENDED = 4;

--
-- Alterac Valley Scoreboard Columns
--
CattleProd_ALTERAC_VALLEY_SCOREBOARD_COLUMNS = {
	CattleProd_ALTERAC_VALLEY_GRAVEYARDS_ASSAULTED,
	CattleProd_ALTERAC_VALLEY_GRAVEYARDS_DEFENDED,
	CattleProd_ALTERAC_VALLEY_TOWERS_ASSAULTED,
	CattleProd_ALTERAC_VALLEY_TOWERS_DEFENDED
};

--
-- Get Alterac Valley scoreboard map.
--
-- playerIndex Player Index
--
-- return Player Scoreboard Map
--
function CattleProd_GetAlteracValleyScoreboardMap(playerIndex)
	CattleProd_AssertType(playerIndex, "number", "Illegal Argument");

	local scoreboard = {};

	for i = 1, # CattleProd_ALTERAC_VALLEY_SCOREBOARD_COLUMNS
	do
		local slotIndex = CattleProd_ALTERAC_VALLEY_SCOREBOARD_COLUMNS[i];
		local count = GetBattlefieldStatData(playerIndex, slotIndex);
		CattleProd_AssertType(count, "number", "Invalid Scoreboard Column: %d", slotIndex);

		scoreboard[slotIndex] = count;
	end

	return scoreboard;
end

--
-- Constant: Alterac Valley - Dun Baldar
--
CattleProd_ALTERAC_VALLEY_DUN_BALDAR = 2;

--
-- Constant: Alterac Valley - Stormpike Aid Station
--
CattleProd_ALTERAC_VALLEY_STORMPIKE_AID_STATION = 19;

--
-- Constant: Alterac Valley - Dun Baldar South Bunker
--
CattleProd_ALTERAC_VALLEY_DUN_BALDAR_SOUTH_BUNKER = 4;

--
-- Constant: Alterac Valley - Dun Baldar North Bunker
--
CattleProd_ALTERAC_VALLEY_DUN_BALDAR_NORTH_BUNKER = 3;

--
-- Constant: Alterac Valley - Coldtooth Mine
--
CattleProd_ALTERAC_VALLEY_COLDTOOTH_MINE = 1;

--
-- Constant: Alterac Valley - Stormpike Graveyard
--
CattleProd_ALTERAC_VALLEY_STORMPIKE_GRAVEYARD = 20;

--
-- Constant: Alterac Valley - Icewing Cavern
--
CattleProd_ALTERAC_VALLEY_ICEWING_CAVERN = 13;

--
-- Constant: Alterac Valley - Icewing Bunker
--
CattleProd_ALTERAC_VALLEY_ICEWING_BUNKER = 12;

--
-- Constant: Alterac Valley - Stonehearth Bunker
--
CattleProd_ALTERAC_VALLEY_STONEHEARTH_BUNKER = 16;

--
-- Constant: Alterac Valley - Stonehearth Outpost
--
CattleProd_ALTERAC_VALLEY_STONEHEARTH_OUTPOST = 18;

--
-- Constant: Alterac Valley - Stonehearth Graveyard
--
CattleProd_ALTERAC_VALLEY_STONEHEARTH_GRAVEYARD = 17;

--
-- Constant: Alterac Valley - Snowfall Graveyard
--
CattleProd_ALTERAC_VALLEY_SNOWFALL_GRAVEYARD = 15;

--
-- Constant: Alterac Valley - Iceblood Garisson
--
CattleProd_ALTERAC_VALLEY_ICEBLOOD_GARISSON = 9;

--
-- Constant: Alterac Valley - Iceblood Tower
--
CattleProd_ALTERAC_VALLEY_ICEBLOOD_TOWER = 11;

--
-- Constant: Alterac Valley - Iceblook Graveyard
--
CattleProd_ALTERAC_VALLEY_ICEBLOOD_GRAVEYARD = 10;

--
-- Constant: Alterac Valley - Tower Point
--
CattleProd_ALTERAC_VALLEY_TOWER_POINT = 21;

--
-- Constant: Alterac Valley - Irondeep Mine
--
CattleProd_ALTERAC_VALLEY_IRONDEEP_MINE = 14;

--
-- Constant: Alterac Valley - Frostwolf Graveyard
--
CattleProd_ALTERAC_VALLEY_FROSTWOLF_GRAVEYARD = 6;

--
-- Constant: Alterac Valley - Wildpaw Cavern
--
CattleProd_ALTERAC_VALLEY_WILDPAW_CAVERN = 23;

--
-- Constant: Alterac Valley - West Frostwolf Tower
--
CattleProd_ALTERAC_VALLEY_WEST_FROSTWOLF_TOWER = 22;

--
-- Constant: Alterac Valley - East Frostwolf Tower
--
CattleProd_ALTERAC_VALLEY_EAST_FROSTWOLF_TOWER = 5;

--
-- Constant: Alterac Valley - Frostwolf Relief Hut
--
CattleProd_ALTERAC_VALLEY_FROSTWOLF_RELIEF_HUT = 8;

--
-- Constant: Alterac Valley - Frostwolf Keep
--
CattleProd_ALTERAC_VALLEY_FROSTWOLF_KEEP = 7;


--
-- Alterac Valley Alliance Defense Order
--
local CattleProd_AlteracValleyAllianceDefenseOrder = {
    CattleProd_ALTERAC_VALLEY_STORMPIKE_AID_STATION,
    CattleProd_ALTERAC_VALLEY_DUN_BALDAR_SOUTH_BUNKER,
    CattleProd_ALTERAC_VALLEY_DUN_BALDAR_NORTH_BUNKER,
    CattleProd_ALTERAC_VALLEY_STORMPIKE_GRAVEYARD,
    CattleProd_ALTERAC_VALLEY_ICEWING_BUNKER,
    CattleProd_ALTERAC_VALLEY_STONEHEARTH_BUNKER,
    CattleProd_ALTERAC_VALLEY_STONEHEARTH_GRAVEYARD,
    CattleProd_ALTERAC_VALLEY_SNOWFALL_GRAVEYARD,
    CattleProd_ALTERAC_VALLEY_ICEBLOOD_TOWER,
    CattleProd_ALTERAC_VALLEY_ICEBLOOD_GRAVEYARD,
    CattleProd_ALTERAC_VALLEY_TOWER_POINT,
    CattleProd_ALTERAC_VALLEY_FROSTWOLF_GRAVEYARD,
    CattleProd_ALTERAC_VALLEY_WEST_FROSTWOLF_TOWER,
    CattleProd_ALTERAC_VALLEY_EAST_FROSTWOLF_TOWER,
    CattleProd_ALTERAC_VALLEY_FROSTWOLF_RELIEF_HUT,
};

--
-- Alterac Valley Alliance Defense Order
--
local CattleProd_AlteracValleyHordeDefenseOrder = {
    CattleProd_ALTERAC_VALLEY_FROSTWOLF_RELIEF_HUT,
    CattleProd_ALTERAC_VALLEY_EAST_FROSTWOLF_TOWER,
    CattleProd_ALTERAC_VALLEY_WEST_FROSTWOLF_TOWER,
    CattleProd_ALTERAC_VALLEY_FROSTWOLF_GRAVEYARD,
    CattleProd_ALTERAC_VALLEY_TOWER_POINT,
    CattleProd_ALTERAC_VALLEY_ICEBLOOD_GRAVEYARD,
    CattleProd_ALTERAC_VALLEY_ICEBLOOD_TOWER,
    CattleProd_ALTERAC_VALLEY_SNOWFALL_GRAVEYARD,
    CattleProd_ALTERAC_VALLEY_STONEHEARTH_GRAVEYARD,
    CattleProd_ALTERAC_VALLEY_STONEHEARTH_BUNKER,
    CattleProd_ALTERAC_VALLEY_ICEWING_BUNKER,
    CattleProd_ALTERAC_VALLEY_STORMPIKE_GRAVEYARD,
    CattleProd_ALTERAC_VALLEY_DUN_BALDAR_NORTH_BUNKER,
    CattleProd_ALTERAC_VALLEY_DUN_BALDAR_SOUTH_BUNKER,
    CattleProd_ALTERAC_VALLEY_STORMPIKE_AID_STATION,
};

--
-- Alterac Valley Defendable Locations
--
local CattleProd_AlteracValleyLocations = {
    [CattleProd_ALTERAC_VALLEY_STORMPIKE_AID_STATION] = { 42.7, 15.8 },
    [CattleProd_ALTERAC_VALLEY_DUN_BALDAR_SOUTH_BUNKER] = { 44.0, 18.4 },
    [CattleProd_ALTERAC_VALLEY_DUN_BALDAR_NORTH_BUNKER] = { 45.1, 14.5 },
    [CattleProd_ALTERAC_VALLEY_STORMPIKE_GRAVEYARD] = { 48.9, 14.5 },
    [CattleProd_ALTERAC_VALLEY_ICEWING_BUNKER] = { 50.7, 30.9 },
    [CattleProd_ALTERAC_VALLEY_STONEHEARTH_BUNKER] = { 52.7, 43.7 },
    [CattleProd_ALTERAC_VALLEY_STONEHEARTH_GRAVEYARD] = { 51.6, 35.6 },
    [CattleProd_ALTERAC_VALLEY_SNOWFALL_GRAVEYARD] = { 44.6, 45.6 },
    [CattleProd_ALTERAC_VALLEY_ICEBLOOD_TOWER] = { 48.2, 58.6 },
    [CattleProd_ALTERAC_VALLEY_ICEBLOOD_GRAVEYARD] = { 51.4, 60.0 },
    [CattleProd_ALTERAC_VALLEY_TOWER_POINT] = { 50.5, 65.6 },
    [CattleProd_ALTERAC_VALLEY_FROSTWOLF_GRAVEYARD] = { 50.1, 76.7 },
    [CattleProd_ALTERAC_VALLEY_WEST_FROSTWOLF_TOWER] = { 48.3, 84.4 },
    [CattleProd_ALTERAC_VALLEY_EAST_FROSTWOLF_TOWER] = { 49.5, 84.6 },
    [CattleProd_ALTERAC_VALLEY_FROSTWOLF_RELIEF_HUT] = { 49.3, 88.1 },
}

--
-- Get Alterac Valley defensible positions map.
--
-- return Defendable Position map
--
-- map: Position => { X, Y }
--
function CattleProd_AlteracValleyDefensiblePositionsMap()
	-- defensible positions map
	local defensiblePositions = {};

	-- defensible states
	local defensibleStates = {};

	-- ordered positions
	local orderedPositions = nil;

	local faction = CattleProd_GetFaction();
	if (faction == 0)
	then
		-- horde
		table.insert(defensibleStates,  1); -- mn c
		table.insert(defensibleStates, 12); -- gy c
		table.insert(defensibleStates, 13); -- gy a
		table.insert(defensibleStates,  9); -- t  c
		table.insert(defensibleStates, 11); -- t  a

		orderedPositions = CattleProd_AlteracValleyHordeDefenseOrder;
	elseif (faction == 1)
	then
		-- alliance
		table.insert(defensibleStates,  2); -- mn c
		table.insert(defensibleStates, 14); -- gy c
		table.insert(defensibleStates,  3); -- gy a
		table.insert(defensibleStates, 10); -- t  c
		table.insert(defensibleStates,  8); -- t  a

		orderedPositions = CattleProd_AlteracValleyAllianceDefenseOrder;
	end

	-- cascading defense
	-- The idea behind cascading defense is that a team will only
	-- have defenders at the next couple nodes that the other team
	-- has not taken.  If a player is defending further back than
	-- the next three nodes, they are likely afking instead of
	-- actually defending.

	local startingTerritory = true;
    
	for i = 1, # orderedPositions
	do
		local landmark = orderedPositions[i];

		-- lookup location
		local name, description, textureIndex, x, y
		name, description, textureIndex, x, y = GetMapLandmarkInfo(landmark);

		if (startingTerritory and
			not CattleProd_Contains(defensibleStates, textureIndex))
		then
			-- add previous three locations as defendable nodes
			-- prior to that people are likely just over defending
			if ((i - 1) > 0)
			then
				local position = orderedPositions[i - 1];
				local location = CattleProd_AlteracValleyLocations[position];
				CattleProd_AssertNotNil(location, "Unknown landmark: %d", landmark);
				table.insert(defensiblePositions, location);
			end
			if ((i - 2) > 0)
			then
				local position = orderedPositions[i - 2];
				local location = CattleProd_AlteracValleyLocations[position];
				CattleProd_AssertNotNil(location, "Unknown landmark: %d", landmark);
				table.insert(defensiblePositions, location);
			end
			if ((i - 3) > 0)
			then
				local position = orderedPositions[i - 3];
				local location = CattleProd_AlteracValleyLocations[position];
				CattleProd_AssertNotNil(location, "Unknown landmark: %d", landmark);
				table.insert(defensiblePositions, location);
			end

			-- the opposing faction's front line has
			-- cut off the starting territory
			startingTerritory = false;
		end

		-- search for skipped nodes if rush offense is set as the
		-- other team seems to have skipped some nodes.
		if (not startingTerritory and
			CattleProd_Contains(defensibleStates, textureIndex))
		then
			local location = CattleProd_AlteracValleyLocations[landmark];
			CattleProd_AssertNotNil(location, "Unknown landmark: %d", landmark);
			table.insert(defensiblePositions, location);
		end
	end

	return defensiblePositions;
end

--
-- Calculate Alterac Valley scoreboard effort.
--
-- scoreboardDelta Scoreboard Delta
--
-- return Effort
--
function CattleProd_CalculateAlteracValleyScoreboardEffort(scoreboardDelta)
	CattleProd_AssertType(scoreboardDelta, "table", "Invalid Argument");	

	local effortTotal = 0;

	-- graveyards assaulted
	local graveyardsAssaulted =
		scoreboardDelta[CattleProd_ALTERAC_VALLEY_GRAVEYARDS_ASSAULTED];
	if (graveyardsAssaulted == nil)
	then
		CattleProd_Warn("graveyardsAssaulted == nil");
	else
		local bonusEffort = CattleProd_GetSetting(
			CattleProd_ALTERAC_VALLEY_GRAVEYARD_ASSAULTED_BONUS_EFFORT);

		local effort = graveyardsAssaulted * bonusEffort;

		effortTotal = effortTotal + effort;
	end

	-- graveyards defended
	local graveyardsDefended =
		scoreboardDelta[CattleProd_ALTERAC_VALLEY_GRAVEYARDS_DEFENDED];
	if (graveyardsDefended == nil)
	then
		CattleProd_Warn("graveyardsDefended == nil");
	else
		local bonusEffort = CattleProd_GetSetting(
			CattleProd_ALTERAC_VALLEY_GRAVEYARD_DEFENDED_BONUS_EFFORT);

		local effort = graveyardsDefended * bonusEffort;

		effortTotal = effortTotal + effort;
	end

	-- towers assaulted
	local towersAssaulted =
		scoreboardDelta[CattleProd_ALTERAC_VALLEY_TOWERS_ASSAULTED];
	if (towersAssaulted == nil)
	then
		CattleProd_Warn("towersAssaulted == nil");
	else
		local bonusEffort = CattleProd_GetSetting(
			CattleProd_ALTERAC_VALLEY_TOWER_ASSAULTED_BONUS_EFFORT);

		local effort = towersAssaulted * bonusEffort;

		effortTotal = effortTotal + effort;
	end

	-- towers defended
	local towersDefended =
		scoreboardDelta[CattleProd_ALTERAC_VALLEY_TOWERS_DEFENDED];
	if (towersDefended == nil)
	then
		CattleProd_Warn("towersDefended == nil");
	else
		local bonusEffort = CattleProd_GetSetting(
			CattleProd_ALTERAC_VALLEY_TOWER_DEFENDED_BONUS_EFFORT);

		local effort = towersDefended * bonusEffort;

		effortTotal = effortTotal + effort;
	end

	return effortTotal;
end

--
-- Get Alterac Valley Defensive Range.
--
-- return Defensive range
--
function CattleProd_GetAlteracValleyDefensiveRange()
	return .85;
end

--
-- Calculate Alterac Valley defender bonus effort.
--
-- defenderCount Defender Count
--
-- return Effort
--
function CattleProd_CalculateAlteracValleyDefenderEffort(defenderCount)
	CattleProd_AssertType(defenderCount, "number", "Invalid Argument");

	-- bonus effort
	local bonusEffort = CattleProd_GetSetting(
		CattleProd_ALTERAC_VALLEY_DEFENDER_BONUS_EFFORT);
	CattleProd_AssertType(bonusEffort, "number", "Setting %s unset",
		CattleProd_ALTERAC_VALLEY_DEFENDER_BONUS_EFFORT);

	return defenderCount * bonusEffort;
end
